﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="CollectionExtensions.cs" company="JDML Consulting Ltd.">
//   Copyright 2011 Photon Project - http://photon.codeplex.com
// </copyright>
// <summary>
//   Defines the CollectionExtensions type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Photon.Collections
{
    using System;
    using System.Collections.Generic;

    public static class CollectionExtensions
    {
        public static void AddRange<T>(this ICollection<T> instance, IEnumerable<T> items)
        {
            var list = instance as List<T>;
            if (list != null)
            {
                list.AddRange(items);
            }
            else
            {
                foreach (var item in items)
                {
                    instance.Add(item);
                }
            }
        }

        public static int RemoveAll<T>(this IList<T> instance, Predicate<T> match)
        {
            Guard.ArgumentNull("match", match);
            
            var index = 0;
            while ((index < instance.Count) && !match(instance[index]))
            {
                index++;
            }

            if (index >= instance.Count)
            {
                return 0;
            }

            var matchIndex = index + 1;
            while (matchIndex < instance.Count)
            {
                while ((matchIndex < instance.Count) && match(instance[matchIndex]))
                {
                    matchIndex++;
                }

                if (matchIndex < instance.Count)
                {
                    instance[index++] = instance[matchIndex++];
                }
            }

            var numberOfItemsRemoved = instance.Count - index;
            instance.Truncate(instance.Count - numberOfItemsRemoved);
            return numberOfItemsRemoved;
        }

        public static int FindIndex<T>(this IList<T> instance, Predicate<T> match)
        {
            var count = instance.Count;
            for (var i = 0; i < count; i++)
            {
                if (match(instance[i]))
                {
                    return i;
                }
            }

            return -1;
        }

        private static void Truncate<T>(this IList<T> instance, int count)
        {
            var list = instance as List<T>;
            if (list != null)
            {
                list.Truncate(count);
            }
            else
            {
                while (instance.Count > count)
                {
                    instance.RemoveAt(instance.Count - 1);
                }
            }
        }

        public static int ForEach<T>(this IEnumerable<T> instance, Action<T> action)
        {
            var index = 0;
            foreach (var item in instance)
            {
                action(item);
                index++;
            }

            return index;
        }

        private static void Truncate<T>(this List<T> instance, int count)
        {
            instance.RemoveRange(count, instance.Count - count);
        }
    }
}
